/*
* @(#)AbstractMaintPermissionAction.java
*
* Copyright (c) 2003 DCIVision Ltd
* All rights reserved.
*
* This software is the confidential and proprietary information of DCIVision
* Ltd ("Confidential Information").  You shall not disclose such Confidential
* Information and shall use it only in accordance with the terms of the license
* agreement you entered into with DCIVision Ltd.
*/
package com.dcivision.setup.web;

import java.sql.Connection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.ActionMapping;

import com.dcivision.dms.bean.DmsDocument;
import com.dcivision.dms.core.DocumentRetrievalManager;
import com.dcivision.framework.ApplicationException;
import com.dcivision.framework.GlobalConstant;
import com.dcivision.framework.PermissionManager;
import com.dcivision.framework.SessionContainer;
import com.dcivision.framework.TextUtility;
import com.dcivision.framework.Utility;
import com.dcivision.framework.web.AbstractActionForm;
import com.dcivision.framework.web.AbstractMaintAction;
import com.dcivision.user.bean.UserGroupPermission;
import com.dcivision.user.bean.UserRecordPermission;
import com.dcivision.user.bean.UserRolePermission;
import com.dcivision.user.dao.UserGroupDAObject;
import com.dcivision.user.dao.UserGroupPermissionDAObject;
import com.dcivision.user.dao.UserRecordDAObject;
import com.dcivision.user.dao.UserRecordPermissionDAObject;
import com.dcivision.user.dao.UserRoleDAObject;
import com.dcivision.user.dao.UserRolePermissionDAObject;

/**
 * This class is an abstract struts action that encapsulates permission setting form
 *
 * @author          Zoe Shum
 * @company         DCIVision Limited
 * @creation date   06/08/2003
 * @version         $Revision: 1.22.2.1 $
 */
 public abstract class AbstractMaintPermissionAction extends AbstractMaintAction {
  protected String objectIDProperty = "ID";

  public AbstractMaintPermissionAction() {
    super();
  }

  public void init(ActionMapping mapping, AbstractActionForm form, HttpServletRequest request, HttpServletResponse response) throws ApplicationException {
    this.selectPermissionObjects(mapping, form, request, response);
  }

  public void selectRecord(ActionMapping mapping, AbstractActionForm form, HttpServletRequest request, HttpServletResponse response) throws ApplicationException {
    // Call super method to handle basic selection function.
    super.selectRecord(mapping, form, request, response);
    this.selectPermissionObjects(mapping, form, request, response);
  }

  public void insertRecord(ActionMapping mapping, AbstractActionForm form, HttpServletRequest request, HttpServletResponse response) throws ApplicationException {
    super.insertRecord(mapping, form, request, response);
    this.updatePermissionObjects(mapping, form, request, response);
  }

  public void updateRecord(ActionMapping mapping, AbstractActionForm form, HttpServletRequest request, HttpServletResponse response) throws ApplicationException {
    super.updateRecord(mapping, form, request, response);
    this.updatePermissionObjects(mapping, form, request, response);
    PermissionManager.firePermissionChanged(getObjectType(), getObjectID(mapping, form, request, response));
  }

  public abstract String getObjectType();

  protected Integer getObjectID(ActionMapping mapping, AbstractActionForm form, HttpServletRequest request, HttpServletResponse response) throws ApplicationException {
    String objectIDStr = null;
    try {
      objectIDStr = org.apache.commons.beanutils.BeanUtils.getProperty(form, this.objectIDProperty);
    } catch (Exception e) {
      log.error("Cannot get the object ID field.", e);
      return(null);
    }
    Integer objectID = TextUtility.parseIntegerObj(objectIDStr);
    return(objectID);
  }

  /**
   * Updates the permission of the object stored in database and then format the latest permission setting and store it in request attributes for front end display.
   * The formatting portion includes getting the latest user/group/role list from database and determine the chosen and choosable list.
   *
   * @param mapping The action mapping
   * @param form The action form
   * @param request The servlet request
   * @param response The servlet response
   * @throw ApplicationException
   * @see #updatePermissionObjects
   * @see #selectPermissionObjects
   */
  public void updatePermissionObjects(ActionMapping mapping, AbstractActionForm form, HttpServletRequest request, HttpServletResponse response) throws ApplicationException {
    SessionContainer sessionCon = this.getSessionContainer(request);
    Connection conn = this.getConnection(request);
    DocumentRetrievalManager docRetrievalManager = new DocumentRetrievalManager(sessionCon, conn);
    Integer objectID = this.getObjectID(mapping, form, request, response);
    
    // barbin add EIP-1657 20070208
    DmsDocument doc = docRetrievalManager.getDocument(objectID);
    List allSubList = new ArrayList();
    List tempList = new ArrayList();
    tempList.add(objectID);
    if(!Utility.isEmpty(doc)){
      allSubList = docRetrievalManager.getAllsubFolderDocIDsByObjectID(tempList,doc.getRootID());
    }
    Iterator iter = allSubList.iterator();
    this.updatePermissionSetting(form, sessionCon, conn, objectID);  
    while(iter.hasNext()){
      Integer  id = (Integer)iter.next();
      PermissionManager.firePermissionChanged(GlobalConstant.OBJECT_TYPE_DOCUMENT,id);
      //this.updatePermissionSetting(form, sessionCon, conn, docID);  
    }    
    // barbin add end
    this.selectPermissionObjects(mapping, form, request, response);
  }

  /**
   * Updates the permission setting of the object, delete the old data from database and re-create it using the new permission passed
   *
   * @param form The action form containing the permission setting data
   * @param sessionCon The SessionContainer object
   * @param response The database connection
   * @param objectID The object ID owning this permission setting
   * @throw ApplicationException
   */
   public void updatePermissionSetting(AbstractActionForm form, SessionContainer sessionCon, Connection conn, Integer objectID) throws ApplicationException {
    AbstractActionPermissionForm permForm = (AbstractActionPermissionForm)form;
    String permData = TextUtility.replaceString(permForm.getAllPermissionData(), "\r", "");
    String[] tmpAry = TextUtility.splitString(permData, "\n");
    if (tmpAry == null) {
      tmpAry = new String[0];
    }

    UserRecordPermissionDAObject userPermDAO = new UserRecordPermissionDAObject(sessionCon, conn);
    UserGroupPermissionDAObject groupPermDAO = new UserGroupPermissionDAObject(sessionCon, conn);
    UserRolePermissionDAObject rolePermDAO = new UserRolePermissionDAObject(sessionCon, conn);

    // Delete the permission records which should not exists.
    List delUserList = new ArrayList();
    List delGroupList = new ArrayList();
    List delRoleList = new ArrayList();
    for (int i = 0; i < tmpAry.length; i++) {
      if (!Utility.isEmpty(tmpAry[i])) {
        String[] rowAry = TextUtility.splitString(tmpAry[i], "\t");

        if (GlobalConstant.SUBJECT_TYPE_USER.equals(rowAry[2])) {
          delUserList.add(rowAry[7]);
        } else if (GlobalConstant.SUBJECT_TYPE_GROUP.equals(rowAry[2])) {
          delGroupList.add(rowAry[7]);
        } else if (GlobalConstant.SUBJECT_TYPE_ROLE.equals(rowAry[2])) {
          delRoleList.add(rowAry[7]);
        }
      }
    }
    userPermDAO.deleteListByObjectTypeObjectID(this.getObjectType(), objectID, delUserList);
    groupPermDAO.deleteListByObjectTypeObjectID(this.getObjectType(), objectID, delGroupList);
    rolePermDAO.deleteListByObjectTypeObjectID(this.getObjectType(), objectID, delRoleList);

    // Insert and update permission records.
    for (int i = 0; i < tmpAry.length; i++) {
      if (!Utility.isEmpty(tmpAry[i])) {
        String[] rowAry = TextUtility.splitString(tmpAry[i], "\t");

        if (GlobalConstant.SUBJECT_TYPE_USER.equals(rowAry[2])) {
          UserRecordPermission userPerm = new UserRecordPermission();

          if (!"-1".equals(rowAry[7])) {
            userPerm = (UserRecordPermission)userPermDAO.getObjectByID(new Integer(rowAry[7]));
          }

          userPerm.setID(new Integer(rowAry[7]));
          userPerm.setObjectType(this.getObjectType());
          userPerm.setObjectID(objectID);
          userPerm.setUserRecordID(new Integer(rowAry[0]));
          userPerm.setPermission(rowAry[3]);
          userPerm.setStartTime(form.parseTimestamp(rowAry[4]));
          userPerm.setEndTime(form.parseTimestamp(rowAry[5]));
          userPerm.setMustFlag(GlobalConstant.TRUE.equals(rowAry[6]));

          if ("-1".equals(rowAry[7])) {
            userPermDAO.insertObject(userPerm);
          } else {
            userPermDAO.updateObject(userPerm);
          }
        } else if (GlobalConstant.SUBJECT_TYPE_GROUP.equals(rowAry[2])) {
          UserGroupPermission groupPerm = new UserGroupPermission();

          if (!"-1".equals(rowAry[7])) {
            groupPerm = (UserGroupPermission)groupPermDAO.getObjectByID(new Integer(rowAry[7]));
          }

          groupPerm.setID(new Integer(rowAry[7]));
          groupPerm.setObjectType(this.getObjectType());
          groupPerm.setObjectID(objectID);
          groupPerm.setUserGroupID(new Integer(rowAry[0]));
          groupPerm.setPermission(rowAry[3]);
          groupPerm.setStartTime(form.parseTimestamp(rowAry[4]));
          groupPerm.setEndTime(form.parseTimestamp(rowAry[5]));
          groupPerm.setMustFlag(GlobalConstant.TRUE.equals(rowAry[6]));

          if ("-1".equals(rowAry[7])) {
            groupPermDAO.insertObject(groupPerm);
          } else {
            groupPermDAO.updateObject(groupPerm);
          }
        } else if (GlobalConstant.SUBJECT_TYPE_ROLE.equals(rowAry[2])) {
          UserRolePermission rolePerm = new UserRolePermission();

          if (!"-1".equals(rowAry[7])) {
            rolePerm = (UserRolePermission)rolePermDAO.getObjectByID(new Integer(rowAry[7]));
          }

          rolePerm.setID(new Integer(rowAry[7]));
          rolePerm.setObjectType(this.getObjectType());
          rolePerm.setObjectID(objectID);
          rolePerm.setUserRoleID(new Integer(rowAry[0]));
          rolePerm.setPermission(rowAry[3]);
          rolePerm.setStartTime(form.parseTimestamp(rowAry[4]));
          rolePerm.setEndTime(form.parseTimestamp(rowAry[5]));
          rolePerm.setMustFlag(GlobalConstant.TRUE.equals(rowAry[6]));

          if ("-1".equals(rowAry[7])) {
            rolePermDAO.insertObject(rolePerm);
          } else {
            rolePermDAO.updateObject(rolePerm);
          }
        }
      }
    }
  }

  /**
   * Formats the latest permission setting and store it in request attributes for front end display.
   * The formatting portion includes getting the latest user/group/role list from database and determine the chosen and choosable list.
   * It will set the following action form properties:<br>
   *
   * <pre>
   *   allPermissionData            - List of users/groups/roles that have been assigned some permissions.
   *   userNoPermissionData    - List of users that have not been assigned any permission.
   *   groupNoPermissionData  - List of groups that have not been assigned any permission.
   *   roleNoPermissionData     - List of roles that have not been assigned any permission.
   * </pre>
   *
   * @param mapping The action mapping
   * @param form The action form
   * @param request The servlet request
   * @param response The servlet response
   * @throw ApplicationException
   */
   public void selectPermissionObjects(ActionMapping mapping, AbstractActionForm form, HttpServletRequest request, HttpServletResponse response) throws ApplicationException {
    AbstractActionPermissionForm permForm = (AbstractActionPermissionForm)form;
    Integer objectID = this.getObjectID(mapping, form, request, response);
    String objectType = this.getObjectType();
    StringBuffer allPermissionData = new StringBuffer();
    StringBuffer userNoPermissionData = new StringBuffer();
    StringBuffer groupNoPermissionData = new StringBuffer();
    StringBuffer roleNoPermissionData = new StringBuffer();

    SessionContainer sessionCon = this.getSessionContainer(request);
    Connection conn = this.getConnection(request);

    if (objectID == null) {
      objectID = new Integer(0);
    }

    // User
    UserRecordDAObject userRecordDAO = new UserRecordDAObject(sessionCon, conn);
    String[][] saUserHasPerm = userRecordDAO.getHasPermissionArrayByObjectTypeObjectID(objectType, objectID);
    String[][] saUserHasNoPerm = userRecordDAO.getHasNoPermissionArrayByObjectTypeObjectID(objectType, objectID);

    // putting all users that has been assigned some permissions into the allPermissionData property
    for (int i = 0; i < saUserHasPerm.length; i++) {
      for (int j = 0; j < saUserHasPerm[i].length; j++) {
        if (j == saUserHasPerm[i].length - 1) {
          if (GlobalConstant.NAV_MODE_CHANGE.equals(form.getNavMode())) {
            allPermissionData.append("-1\n");
          } else {
            allPermissionData.append(saUserHasPerm[i][j] + "\n");
          }
        } else {
          allPermissionData.append(saUserHasPerm[i][j] + "\t");
        }
      }
    }

    // putting all users that has not been assigned any permission into the userNoPermissionData property
    for (int i = 0; i < saUserHasNoPerm.length; i++) {
      for (int j = 0; j < saUserHasNoPerm[i].length; j++) {
        if (j == saUserHasNoPerm[i].length - 1) {
          userNoPermissionData.append(saUserHasNoPerm[i][j] + "\n");
        } else {
          userNoPermissionData.append(saUserHasNoPerm[i][j] + "\t");
        }
      }
    }
    permForm.setUserNoPermissionData(userNoPermissionData.toString());

    // Group
    UserGroupDAObject userGroupDAO = new UserGroupDAObject(sessionCon, conn);
    String[][] saGroupHasPerm = userGroupDAO.getHasPermissionArrayByObjectTypeObjectID(objectType, objectID);
    String[][] saGroupHasNoPerm = userGroupDAO.getHasNoPermissionArrayByObjectTypeObjectID(objectType, objectID);

    // putting all groups that has been assigned some permissions into the allPermissionData property
    for (int i = 0; i < saGroupHasPerm.length; i++) {
      for (int j = 0; j < saGroupHasPerm[i].length; j++) {
        if (j == saGroupHasPerm[i].length - 1) {
          if (GlobalConstant.NAV_MODE_CHANGE.equals(form.getNavMode())) {
            allPermissionData.append("-1\n");
          } else {
            allPermissionData.append(saGroupHasPerm[i][j] + "\n");
          }
        } else {
          allPermissionData.append(saGroupHasPerm[i][j] + "\t");
        }
      }
    }

    // putting all groups that has not been assigned any permission into the groupNoPermissionData property
    for (int i = 0; i < saGroupHasNoPerm.length; i++) {
      for (int j = 0; j < saGroupHasNoPerm[i].length; j++) {
        if (j == saGroupHasNoPerm[i].length - 1) {
          groupNoPermissionData.append(saGroupHasNoPerm[i][j] + "\n");
        } else {
          groupNoPermissionData.append(saGroupHasNoPerm[i][j] + "\t");
        }
      }
    }
    permForm.setGroupNoPermissionData(groupNoPermissionData.toString());

    // Role
    UserRoleDAObject userRoleDAO = new UserRoleDAObject(sessionCon, conn);
    String[][] saRoleHasPerm = userRoleDAO.getHasPermissionArrayByObjectTypeObjectID(objectType, objectID);
    String[][] saRoleHasNoPerm = userRoleDAO.getHasNoPermissionArrayByObjectTypeObjectID(objectType, objectID);

    // putting all roles that has been assigned some permissions into the allPermissionData property
    for (int i = 0; i < saRoleHasPerm.length; i++) {
      for (int j = 0; j < saRoleHasPerm[i].length; j++) {
        if (j == saRoleHasPerm[i].length - 1) {
          if (GlobalConstant.NAV_MODE_CHANGE.equals(form.getNavMode())) {
            allPermissionData.append("-1\n");
          } else {
            allPermissionData.append(saRoleHasPerm[i][j] + "\n");
          }
        } else {
          allPermissionData.append(saRoleHasPerm[i][j] + "\t");
        }
      }
    }

    // putting all roles that has not been assigned any permission into the roleNoPermissionData property
    for (int i = 0; i < saRoleHasNoPerm.length; i++) {
      for (int j = 0; j < saRoleHasNoPerm[i].length; j++) {
        if (j == saRoleHasNoPerm[i].length - 1) {
          roleNoPermissionData.append(saRoleHasNoPerm[i][j] + "\n");
        } else {
          roleNoPermissionData.append(saRoleHasNoPerm[i][j] + "\t");
        }
      }
    }
    permForm.setRoleNoPermissionData(roleNoPermissionData.toString());

    permForm.setAllPermissionData(allPermissionData.toString());
  }

}